package cn.shengchao.examstar.gankao.acl.adapters.repositories;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.shengchao.examstar.gankao.acl.ports.repositories.IGanKaoRepository;
import cn.shengchao.examstar.gankao.http.GanKaoHttpRequest;
import cn.shengchao.examstar.gankao.http.GanKaoHttpUtil;
import cn.shengchao.examstar.gankao.infrastrure.po.*;
import cn.shengchao.examstar.gankao.infrastrure.service.*;
import cn.shengchao.examstar.rpc.gankao.GanKaoOrderGoodsListDto;
import cn.shengchao.examstar.rpc.orders.api.IOrderRpc;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @program: examstarapi
 * @description: 赶考网对接业务处理
 * @author: Xiong weiqiang
 * @create: 2025-06-23 17:34
 */
@Service
@RequiredArgsConstructor
public class GanKaoRepository implements IGanKaoRepository {
    @Autowired
    private GanKaoHttpUtil ganKaoHttpUtil;
    @Autowired
    private GkSyncTaskService gkSyncTaskService;
    @Autowired
    private GkGradeService gkGradeService;
    @Autowired
    private GkSubjectService gkSubjectService;
    @Autowired
    private GkGradeSubjectService gkGradeSubjectService;
    @Autowired
    private GkSubjectCategoryService gkSubjectCategoriesService;
    @Autowired
    private GkSubjectCategoryCourseTypeTagService gkSubjectCategoryCourseTypeTagService;
    @Autowired
    private GkSpecTypeMatchService gkSpecTypeMatchService;
    @Autowired
    private GkCourseService gkCourseService;
    @Autowired
    private GkLessonService gkLessonService;
    @Autowired
    private GkSectionService gkSectionService;
    @Autowired
    private GkUserService gkUserService;
    @Autowired
    private GkUserSectionService gkUserSectionService;
    @Autowired
    private GkOrderService gkOrderService;
    @Autowired
    private GkOrderItemService gkOrderItemService;
    @Autowired
    private GkSpecialTagCourseService gkSpecialTagCourseService;
    @Autowired
    private GkSpecialTagTypeMatchService specialTagTypeMatchService;
    @DubboReference
    private final IOrderRpc orderRpc;

    @Override
    public Long getMaxFinishLoadVersion() {
        List<GkSyncTask> gkSyncTasks = gkSyncTaskService.list(new LambdaQueryWrapper<>(GkSyncTask.class).eq(GkSyncTask::getLoadStatus, 1).orderByDesc(GkSyncTask::getLoadVersion));
        if (CollUtil.isNotEmpty(gkSyncTasks)) {
            return gkSyncTasks.getFirst().getLoadVersion();
        }
        return 0L;
    }

    @Override
    public void createLoadVersion(Long loadVersion) {
        GkSyncTask gkSyncTask = new GkSyncTask();
        gkSyncTask.setLoadVersion(loadVersion);
        gkSyncTask.setLoadStatus(0);
        gkSyncTask.setSyncLocalStatus(0);
        gkSyncTaskService.save(gkSyncTask);
    }



    @Override
    public GkSyncTask findNeedLoadTask() {
        java.util.List<GkSyncTask> gkSyncTasks = gkSyncTaskService.list(new LambdaQueryWrapper<>(GkSyncTask.class).eq(GkSyncTask::getLoadStatus, 0).orderByDesc(GkSyncTask::getLoadVersion));
        if (CollUtil.isNotEmpty(gkSyncTasks)) {
            return gkSyncTasks.getFirst();
        }
        return null;
    }
    @Override
    public GkSyncTask findNeedLoadDetailTask() {
        java.util.List<GkSyncTask> gkSyncTasks = gkSyncTaskService.list(new LambdaQueryWrapper<>(GkSyncTask.class).eq(GkSyncTask::getLoadDetailStatus, 0).orderByDesc(GkSyncTask::getLoadVersion));
        if (CollUtil.isNotEmpty(gkSyncTasks)) {
            return gkSyncTasks.getFirst();
        }
        return null;
    }
    @Override
    public void saveBatchGrade(List<GkGrade> gkGradeList) {
        gkGradeService.saveBatch(gkGradeList);
    }

    @Override
    public void saveBatchSubject(List<GkSubject> gkSubjectList) {
        gkSubjectService.saveBatch(gkSubjectList);
    }

    @Override
    public void saveBatchGradeSubject(List<GkGradeSubject> gradeSubjectList) {
        gkGradeSubjectService.saveBatch(gradeSubjectList);
    }

    @Override
    public void saveBatchCourse(List<GkCourse> gkCourses) {
        gkCourseService.saveBatch(gkCourses);
    }

    @Override
    public void finishDataLoadTaskByLoadVersion(Long loadVersion) {
        GkSyncTask gkSyncTask = gkSyncTaskService.getBaseMapper().selectOne(Wrappers.lambdaQuery(GkSyncTask.class)
                .eq(GkSyncTask::getLoadVersion, loadVersion)
        );
        if (gkSyncTask != null) {
            gkSyncTask.setLoadStatus(1);
            gkSyncTask.setLoadTime(new Date());
            gkSyncTask.setSyncLocalStatus(0);
            gkSyncTask.setLoadMsg("加载成功");
            gkSyncTaskService.updateById(gkSyncTask);
        }
    }

    @Override
    public void finishSpecialLoadTaskByLoadVersion(Long loadVersion) {
        GkSyncTask gkSyncTask = gkSyncTaskService.getBaseMapper().selectOne(Wrappers.lambdaQuery(GkSyncTask.class)
                .eq(GkSyncTask::getLoadVersion, loadVersion)
        );
        if (gkSyncTask != null) {
            gkSyncTask.setLoadSpecialStatus(1);
            gkSyncTask.setLoadTime(new Date());
            gkSyncTask.setSyncLocalStatus(0);
            gkSyncTask.setLoadMsg("加载成功");
            gkSyncTaskService.updateById(gkSyncTask);
        }
    }

    @Override
    public void finishCourseDetailLoadTaskByLoadVersion(Long loadVersion) {
        GkSyncTask gkSyncTask = gkSyncTaskService.getBaseMapper().selectOne(Wrappers.lambdaQuery(GkSyncTask.class)
                .eq(GkSyncTask::getLoadVersion, loadVersion)
        );
        long count = gkCourseService.count(Wrappers.lambdaQuery(GkCourse.class).eq(GkCourse::getLoadVersion,loadVersion)
                .eq(GkCourse::getLoadStatus,0)
        );
        if (gkSyncTask != null&&count==0) {
            gkSyncTask.setLoadDetailStatus(1);
            gkSyncTask.setLoadTime(new Date());
            gkSyncTask.setSyncLocalStatus(0);
            gkSyncTask.setLoadMsg("加载详情成功");
            gkSyncTaskService.updateById(gkSyncTask);
        }
    }

    @Override
    public List<GkCourse> loadNotLoadDetailCourse(Long loadVersion) {
        return gkCourseService.list(Wrappers.lambdaQuery(GkCourse.class).eq(ObjectUtil.isNotNull(loadVersion), GkCourse::getLoadVersion, loadVersion).eq(GkCourse::getLoadStatus, 0).orderByDesc(GkCourse::getId).last("limit 100"));
    }

    @Override
    public List<GkCourse> loadNotLoadDetailCourseInSpecialTag(Long loadVersion, String tag) {
        return gkCourseService.loadNotLoadDetailCourseInSpecialTag(loadVersion.toString(), tag,50);
    }

    @Override
    public void saveBatchSpecTagCourse(List<GkSpecialTagCourse> gkSpecialTagCourses) {
        gkSpecialTagCourseService.saveBatch(gkSpecialTagCourses);
    }

    @Override
    public void saveBatchLesson(List<Long> courseDataIds, List<GkLesson> lessons, List<GkSection> gkSections) {
        if (CollUtil.isNotEmpty(courseDataIds)) {
            if (CollUtil.isNotEmpty(lessons)) {
                Long loadVersion = lessons.getFirst().getLoadVersion();
                Integer courseId = lessons.getFirst().getCourseId();
                gkLessonService.remove(Wrappers.lambdaQuery(GkLesson.class).eq(GkLesson::getLoadVersion, loadVersion).eq(GkLesson::getCourseId, courseId));
                gkLessonService.saveBatch(lessons);
                if (CollUtil.isNotEmpty(gkSections)) {
                    gkSectionService.remove(Wrappers.lambdaQuery(GkSection.class).eq(GkSection::getLoadVersion, loadVersion).eq(GkSection::getCourseId, courseId));
                    gkSectionService.saveBatch(gkSections);
                }
            }
            gkCourseService.update(Wrappers.lambdaUpdate(GkCourse.class).in(GkCourse::getId, courseDataIds).set(GkCourse::getLoadStatus, 1));
        }
    }

    @Override
    public void saveBatchCourseCategoryByCheck(Long loadVersion, int gradeId, int subjectId, List<GkSubjectCategory> gkSubjectCategories) {
        long count= gkSubjectCategoriesService.count(Wrappers.lambdaQuery(GkSubjectCategory.class).eq(GkSubjectCategory::getLoadVersion, loadVersion).eq(GkSubjectCategory::getGradeId, gradeId).eq(GkSubjectCategory::getSubjectId, subjectId));
        if (count==0){
            gkSubjectCategoriesService.saveBatch(gkSubjectCategories);
        }
    }

    @Override
    public void saveBatchCourseCategoryCourseTypeTag(List<GkSubjectCategoryCourseTypeTag> gkSubjectCategoryCourseTypeTagList) {
        if (CollUtil.isNotEmpty(gkSubjectCategoryCourseTypeTagList)){
            gkSubjectCategoryCourseTypeTagService.saveBatch(gkSubjectCategoryCourseTypeTagList);
        }
    }

    @Override
    public void updateCourseLoadStatusAndDetail(Long loadVersion, Map<Integer, String> courseDetailMap) {
        if (CollUtil.isNotEmpty(courseDetailMap)){
            courseDetailMap.forEach((courseId, description) -> {
                gkCourseService.update(Wrappers.lambdaUpdate(GkCourse.class)
                        .eq(GkCourse::getLoadVersion, loadVersion)
                        .eq(GkCourse::getCourseId, courseId).set(GkCourse::getLoadStatus, 1).set(GkCourse::getDescription, description));
            });
        }
    }

    @Override
    public List<GkGradeSubject> listAllGradeSubjects() {
        List<GkGradeSubject> gkGradeSubjectList=gkGradeSubjectService.list();
        if (CollUtil.isNotEmpty(gkGradeSubjectList)){
            return gkGradeSubjectList;
        }
        return List.of();
    }

    @Override
    public List<GkGrade> listAllGrades() {
        List<GkGrade> gkGradeList=gkGradeService.list();
        if (CollUtil.isNotEmpty(gkGradeList)){
            return gkGradeList;
        }
        return List.of();
    }

    @Override
    public List<GkSubject> listAllSubjects() {
        List<GkSubject> gkSubjectList =gkSubjectService.list();
        if (CollUtil.isNotEmpty(gkSubjectList)){
            return gkSubjectList;
        }
        return List.of();
    }

    @Override
    public List<GkSubjectCategory> listSubjectCategorys(String number, Integer gradeId, Integer subjectId) {
        return gkSubjectCategoriesService.list(Wrappers.lambdaQuery(GkSubjectCategory.class)
                .eq(GkSubjectCategory::getLoadVersion,number)
                .eq(GkSubjectCategory::getGradeId, gradeId)
                .eq(GkSubjectCategory::getSubjectId, subjectId));
    }

    @Override
    public void saveGradeSpecMatch(Integer gradeId,Long specId ) {
        GkSpecTypeMatch gkSpecTypeMatch = new GkSpecTypeMatch();
        gkSpecTypeMatch.setSpecificationTypeId(specId.toString());
        gkSpecTypeMatch.setGradeId(gradeId);
        gkSpecTypeMatch.setCateId(0);
        gkSpecTypeMatch.setSubjectId(0);
        gkSpecTypeMatch.setParentId(0);
        gkSpecTypeMatchService.save(gkSpecTypeMatch);
    }

    @Override
    public void saveSubjectSpecMatch(Integer gradeId, Integer subjectId, Long specId) {
        GkSpecTypeMatch gkSpecTypeMatch = new GkSpecTypeMatch();
        gkSpecTypeMatch.setSpecificationTypeId(specId.toString());
        gkSpecTypeMatch.setGradeId(gradeId);
        gkSpecTypeMatch.setCateId(0);
        gkSpecTypeMatch.setParentId(0);
        gkSpecTypeMatch.setSubjectId(subjectId);
        gkSpecTypeMatchService.save(gkSpecTypeMatch);
    }

    @Override
    public void saveSubjectCateSpecMatch(Integer gradeId, Integer subjectId, Integer cateId, Integer parentId,Long specId) {
        GkSpecTypeMatch gkSpecTypeMatch = new GkSpecTypeMatch();
        gkSpecTypeMatch.setSpecificationTypeId(specId.toString());
        gkSpecTypeMatch.setGradeId(gradeId);
        gkSpecTypeMatch.setCateId(cateId);
        gkSpecTypeMatch.setParentId(parentId);
        gkSpecTypeMatch.setSubjectId(subjectId);
        gkSpecTypeMatchService.save(gkSpecTypeMatch);
    }

    @Override
    public List<GkCourse> loadAllCourse(Long loadVersion) {
        List<GkCourse> gkCourse=gkCourseService.list(Wrappers.lambdaQuery(GkCourse.class).eq(GkCourse::getLoadVersion, loadVersion));
        if (CollUtil.isNotEmpty(gkCourse)){
            return gkCourse;
        }
        return List.of();
    }

    @Override
    public List<GkCourse> loadCourseTypeNotSyncLocalCourse(String loadVersion, int courseType, int lastLimit) {
        return gkCourseService.loadCourseTypeNotSyncLocalCourse(loadVersion,courseType,lastLimit);
    }

    @Override
    public List<GkCourse> loadCourseTagNotSyncLocalCourse(String loadVersion, String tag, int lastLimit) {
        return gkCourseService.loadCourseTagNotSyncLocalCourse(loadVersion,tag,lastLimit);
    }

    @Override
    public List<GkCourse> loadCourseTypeNotSpecCourse(String loadVersion, int courseType, int lastLimit) {
        return gkCourseService.loadCourseTypeNotSpecTypeCourse(loadVersion,courseType,lastLimit);
    }

    @Override
    public void updateCourseSyncStatusAndDetail(Long loadVersion, List<Integer> courseIds) {
        if (CollUtil.isNotEmpty(courseIds)) {
            gkCourseService.update(Wrappers.lambdaUpdate(GkCourse.class).eq(GkCourse::getLoadVersion, loadVersion).eq(GkCourse::getSyncStatus, 0).in(GkCourse::getCourseId, courseIds).set(GkCourse::getSyncStatus, 1));
        }
    }

    @Override
    public List<GkLesson> loadSessionByCourseId(Long loadVersion, Integer id) {
        return gkLessonService.list(Wrappers.lambdaQuery(GkLesson.class).eq(GkLesson::getCourseId, id).eq(GkLesson::getLoadVersion, loadVersion));
    }

    @Override
    public List<GkSection> loadSectionByCourseIdAndLesson(Long loadVersion, Integer courseId, Integer o) {
        return gkSectionService.list(Wrappers.lambdaQuery(GkSection.class).eq(ObjectUtil.isNotNull( courseId),GkSection::getCourseId, courseId).eq(ObjectUtil.isNotNull( o),GkSection::getLessonId, o).eq(GkSection::getLoadVersion, loadVersion));
    }

    @Override
    public List<GkSpecTypeMatch> listSpecificationTypeIdByCateId(Integer cateId) {
        return gkSpecTypeMatchService.list(Wrappers.lambdaQuery(GkSpecTypeMatch.class).eq(GkSpecTypeMatch::getCateId, cateId));
    }

    @Override
    public boolean checkOrderCourseAndSync(String orderId,Date orderTime, BigDecimal amount, Long userId,List<GanKaoOrderGoodsListDto> goodsListDtoList) {
        GkUser gkUser=gkUserService.getIfExist(userId);
        String result=ganKaoHttpUtil.requestBuySection(gkUser.getUserId(),orderId,amount,goodsListDtoList);
        JSONObject jsonObject= GanKaoHttpRequest.getResultIfSuccess(result);
        if (jsonObject!=null){
            String partnerOrderId=jsonObject.getJSONObject("data").getStr("partnerOrderId");
            GkOrder gkOrder=new GkOrder();
            gkOrder.setUserId(userId);
            gkOrder.setGkOrderId(partnerOrderId);
            gkOrder.setSysOrderId(orderId);
            gkOrder.setOrderTime(orderTime);
            List<GkOrderItem> goodsList=new ArrayList<>();
            for (GanKaoOrderGoodsListDto goodsListDto:goodsListDtoList){
                GkOrderItem gkOrderItem=new GkOrderItem();
                gkOrderItem.setGkOrderId(partnerOrderId);
                gkOrderItem.setSectionId(goodsListDto.getSectionId());
                gkOrderItem.setExpiredDay(goodsListDto.getExpiredDays());
                gkOrderItem.setPrice(goodsListDto.getPrice());
                goodsList.add(gkOrderItem);
            }
            gkOrderService.save(gkOrder);
            gkOrderItemService.saveBatch(goodsList);
            return true;
        }
        return false ;
    }

    @Override
    public void loadAndRefreshUserCourseExpired(Long id) {
        String result=ganKaoHttpUtil.requestGetUserSections(id.toString());
        JSONObject jsonObject= GanKaoHttpRequest.getResultIfSuccess(result);
        if (jsonObject!=null){
            JSONArray gkUserSections=jsonObject.getJSONObject("data").getJSONArray("userSections");
            if (CollUtil.isNotEmpty(gkUserSections)){
                List<GkUserSection> gkUserSectionList=new ArrayList<>();
                for (Object item:gkUserSections){
                    GkUserSection gkUserSection=new GkUserSection();
                    JSONObject jsonObj=new JSONObject(item);
//              {"course_id":null,"lesson_id":"37","section_id":"37","user_id":"16110307","created_at":"2025-06-25 14:38:51","expires":"2025-06-26 14:38:51","is_expired":0},
                    gkUserSection.setUserId(id.toString());
                    gkUserSection.setCourseId(jsonObj.getInt("course_id"));
                    gkUserSection.setLessonId(jsonObj.getInt("lesson_id"));
                    gkUserSection.setSectionId(jsonObj.getInt("section_id"));
                    gkUserSection.setCreatedAt(jsonObj.getStr("created_at"));
                    gkUserSection.setExpires(jsonObj.getStr("expires"));
                    gkUserSection.setIsExpired(jsonObj.getInt("is_expired"));
                    gkUserSection.setDataStatus(1);
                    gkUserSectionList.add(gkUserSection);
                }
                if (CollUtil.isNotEmpty(gkUserSectionList)){
                    gkUserSectionService.update(Wrappers.lambdaUpdate(GkUserSection.class).eq(GkUserSection::getUserId,id).eq(GkUserSection::getDataStatus,1).set(GkUserSection::getDataStatus,2));
                    gkUserSectionService.saveBatch(gkUserSectionList);
                }
            }

        }

    }

    @Override
    public String findSpecTypeIdForCourseTag(String tag) {
        String specTypeId="0";
        List<GkSpecialTagTypeMatch> gkSpecialTagTypeMatchList=specialTagTypeMatchService.list(Wrappers.lambdaQuery(GkSpecialTagTypeMatch.class).eq(GkSpecialTagTypeMatch::getSpecTag,tag));
        if (CollUtil.isNotEmpty(gkSpecialTagTypeMatchList)){
            specTypeId=gkSpecialTagTypeMatchList.getFirst().getSpecificationTypeId();
        }
        return specTypeId;
    }

    @Override
    public List<GkCourse> selectCourseByCourseIds(Long loadVersion, List<Integer> courseIds) {
        if (CollUtil.isNotEmpty(courseIds)){
            return gkCourseService.list(Wrappers.lambdaQuery(GkCourse.class).in(GkCourse::getCourseId, courseIds));

        }else{
            return List.of();
        }
    }

    @Override
    public List<GkCourse> localCourseNeedCreateSpec(Long loadVersion, int limit) {
        return gkCourseService.list(Wrappers.lambdaQuery(GkCourse.class)
                .eq(GkCourse::getLoadVersion, loadVersion).eq(GkCourse::getSyncStatus,1).eq(GkCourse::getSpecStatus,0).orderByDesc(GkCourse::getCourseId)
                .last("limit "+limit)
        );
    }

    @Override
    public List<String> findLocalSpecTypeIdsFromTagMatchForGanKaoCourseId(Integer ganKaoCourseId) {
        return specialTagTypeMatchService.findLocalSpecTypeIdsFromTagMatchForGanKaoCourseId(ganKaoCourseId);
    }

    @Override
    public List<String> findLocalSpecTypeIdsFromSubjectMatchForGanKaoCourseId(Integer ganKaoCourseId) {
        return gkSpecTypeMatchService.findLocalSpecTypeIdsFromSubjectMatchForGanKaoCourseId(ganKaoCourseId);
    }

    @Override
    public void updateCourseSpecStatus(Long loadVersion, Integer courseId) {
        gkCourseService.update(Wrappers.lambdaUpdate(GkCourse.class)
                .eq(GkCourse::getCourseId, courseId).eq(GkCourse::getLoadVersion, loadVersion)
                .set(GkCourse::getSpecStatus, 1));
    }
}